package com.yxy.springcloud.framework.common.redis;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException;

import javax.annotation.PreDestroy;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * author: yuxiaoyang
 *
 * @version1.0
 */
@Service
public class RedisUtils {

  public static Logger logger = LoggerFactory.getLogger(RedisUtils.class);

  @Autowired
  private JedisPool pool;

  //分布式锁相关
  private static final String LOCK_SUCCESS = "OK";
  private static final String SET_IF_NOT_EXIST = "nx";
  private static final String SET_WITH_EXPIRE_TIME = "ex";
  private static final Long RELEASE_SUCCESS = 1L;
  //end

  @PreDestroy
  public void destroyPool() {
    if (pool != null) {
      logger.info("销毁redis pool...");
      pool.destroy();
      pool = null;
    }
  }

  public Jedis getJedis() {
    Jedis jedis = null;
    try {
      jedis = pool.getResource();
    } catch (JedisConnectionException e) {
      logger.error("获取redis链接失败", e);
    } catch (Exception ex) {
      logger.error("", ex);
    }
    return jedis;
  }

  public String get(String key) {
    Jedis jedis = getJedis();
    try {
      return jedis.get(key);
    } finally {
      jedis.close();
    }
  }

  public byte[] get(byte[] key) {
    Jedis jedis = getJedis();
    try {
      return jedis.get(key);
    } finally {
      jedis.close();
    }

  }

  public long expire(String key, int seconds) {
    Jedis jedis = getJedis();
    try {
      return jedis.expire(key, seconds);
    } finally {
      jedis.close();

    }

  }

  public String set(String key, String value) {
    Jedis jedis = getJedis();
    if (jedis == null) {
      logger.error("redis链接为null ");
    }
    try {
      return jedis.set(key, value);
    } finally {
      jedis.close();
    }
  }

  /**
   *
   * @param key
   * @param value
   * @param expireTime 单位 s
   * @return
   */
  public String setEx(String key, String value, int expireTime) {
    Jedis jedis = getJedis();
    if (jedis == null) {
      logger.error("redis链接为null ");
    }
    try {
      return jedis.setex(key, expireTime, value);
    } finally {
      jedis.close();
    }
  }

  public long hset(Jedis jedis, String key, String field, String value) {
    if (jedis == null) {
      logger.error("redis链接为null ");
    }
    return jedis.hset(key, field, value);
  }

  public String hmset(String key, Map<String, String> hash) {
    Jedis jedis = getJedis();
    try {
      return jedis.hmset(key, hash);
    } finally {
      jedis.close();
    }
  }

  public long hset(String key, String field, String value) {
    Jedis jedis = getJedis();
    try {
      return jedis.hset(key, field, value);
    } finally {
      jedis.close();
    }
  }

  public String hget(String key, String field) {
    Jedis jedis = getJedis();
    try {
      return jedis.hget(key, field);
    } finally {
      jedis.close();
    }
  }

  public Map<String, String> hgetAll(String key) {
    Jedis jedis = getJedis();
    try {
      return jedis.hgetAll(key);
    } finally {
      jedis.close();
    }
  }

  public Long hdel(String key, String... fields) {
    Jedis jedis = getJedis();
    try {
      return jedis.hdel(key, fields);
    } finally {
      jedis.close();
    }
  }

  public Boolean exists(String key) {
    Jedis jedis = getJedis();
    try {
      return jedis.exists(key);
    } finally {
      jedis.close();
    }
  }

  public Long incr(String key) {
    Jedis jedis = getJedis();
    try {
      return jedis.incr(key);
    } finally {
      jedis.close();
    }
  }

  public Long lpush(String key, String... values) {
    Jedis jedis = getJedis();
    try {
      return jedis.lpush(key, values);
    } finally {
      jedis.close();
    }

  }

  public Long rpush(String key, String... values) {
    Jedis jedis = getJedis();
    try {
      return jedis.rpush(key, values);
    } finally {
      jedis.close();
    }
  }

  public Long llen(String key) {
    Jedis jedis = getJedis();
    try {
      return jedis.llen(key);
    } finally {
      jedis.close();
    }
  }

  public Long lrem(String key, long count, String value) {
    Jedis jedis = getJedis();
    try {
      return jedis.lrem(key, count, value);
    } finally {
      jedis.close();
    }
  }

  public List<String> lrange(String key, long start, long end) {
    Jedis jedis = getJedis();
    try {
      return jedis.lrange(key, start, end);
    } finally {
      jedis.close();
    }
  }

  public List<String> lrangeAll(String key) {
    return lrange(key, 0, -1);
  }

  public Long hlen(String key) {
    Jedis jedis = getJedis();
    try {
      return jedis.hlen(key);
    } finally {
      jedis.close();
    }
  }

  /**
   * 获取以param开头的 key的数量
   *
   * @param param
   * @return
   * @author icedmaze
   */
  public int getCountKeyLK(String param) {
    Jedis jedis = getJedis();
    try {
      return jedis.keys(param + "*").size();
    } finally {
      jedis.close();
    }
  }

  /**
   * 设置有时效的key 如果已经存在key 则返回null
   *
   * @param key
   * @param value
   * @param time  秒
   * @return
   * @author icedmaze
   */
  public String set(String key, String value, long time) {
    Jedis jedis = getJedis();
    try {
      return jedis.set(key, value, "nx", "ex", time);
    } finally {
      jedis.close();
    }
  }

  /**
   * 根据key删除
   *
   * @param key
   * @return
   * @author icedmazes
   */
  public long del(String key) {
    Jedis jedis = getJedis();
    try {
      return jedis.del(key);
    } finally {
      jedis.close();
    }
  }

  public long hincrBy(String key, String field, long value) {
    Jedis jedis = getJedis();
    try {
      return jedis.hincrBy(key, field, value);
    } finally {
      jedis.close();
    }
  }

  /**
   * 尝试获取分布式锁
   *
   * @param lockKey    锁
   * @param requestId  请求标识
   * @param expireTime 超期时间
   * @return 是否获取成功
   */
  public boolean tryGetDistributedLock(String lockKey, String requestId, int expireTime) throws Exception {
    Jedis jedis = getJedis();
    if (jedis == null) {
      logger.error("获取分布式锁时redis链接为null ");
      throw new Exception("获取分布式锁时redis链接为null");
    }
    String result = jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
    //String result = jedis.set(lockKey, requestId);
    jedis.close();
    if (LOCK_SUCCESS.equals(result)) {
      return true;
    }
    return false;

  }

  /**
   * 释放分布式锁
   *
   * @param lockKey   锁
   * @param requestId 请求标识
   * @return 是否释放成功
   */
  public boolean releaseDistributedLock(String lockKey, String requestId) {
    Jedis jedis = getJedis();
    if (jedis == null) {
      logger.error("释放分布式锁时redis链接为null");
      return false;
    }

    String script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
    Object result = jedis.eval(script, Collections.singletonList(lockKey), Collections.singletonList(requestId));
    jedis.close();
    if (RELEASE_SUCCESS.equals(result)) {
      return true;
    }
    return false;
  }

}
